///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include <Texture/Texture.h>
#include <Texture/ITextureLoader.h>
#include <File/LocalFile.h>
#include <Util.h>

//-----------------------------------------------------------------------------

Texture::Texture ()
{
	m_type = m_format = m_width = m_height = m_texID = 0;
	setLoaded ( false );
}

//-----------------------------------------------------------------------------

Texture::Texture ( std::string name )
{
	m_type = m_format = m_width = m_height = m_texID = 0;
	setLoaded( false );
	m_filename = name;
}

//-----------------------------------------------------------------------------

void Texture::Release ()
{
	if ( isLoaded () )
	{
		glDeleteTextures ( 1, &m_texID );
		GL_CHECK_ERRORS();
		setLoaded ( false );
	}
}

//-----------------------------------------------------------------------------

bool Texture::IsThisTexture( std::string& filename )
{
	return m_filename == filename;
}

//-----------------------------------------------------------------------------

bool	Texture::Load ( GLuint texId )
{
	bool result = true;
	result &= glIsTexture( texId ) == GL_TRUE;
	if( !result ) return result;
	glBindTexture( GL_TEXTURE_2D, texId );
	GLint x;
	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &x);
	m_width = x;
	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &x);
	m_height = x;
	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &x);
	m_format = x;
	glBindTexture( GL_TEXTURE_2D, 0 );
	result &= m_width > 0 && m_height > 0;
	if( !result ) return result;
	m_texID = texId;
	m_type = GL_UNSIGNED_BYTE;
	setLoaded( result );
	return result;
}

//-----------------------------------------------------------------------------

bool Texture::Load ( std::string& filename )
{
	LocalFile*	texFile = MGL_NEW LocalFile( filename.c_str() );
	if( !texFile || !texFile->IsOpen() )
	{
		DEBUG_WAR( "[Texture::Load] Could not open '%s' file!", filename.c_str() );
		return false;
	}

	ITextureLoader* loader =  ITextureLoader::GetLoaderForFile( texFile );
	if( !loader )
	{
		return false;
	}

	if ( isLoaded () )
	{
		Release ();
	}

	glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
	GL_CHECK_ERRORS();
	glGenTextures ( 1, &m_texID );
	GL_CHECK_ERRORS();
	glBindTexture ( GL_TEXTURE_2D, m_texID );
	GL_CHECK_ERRORS();
	setLoaded ( true );

	u8 *data = NULL;

	s32 read = loader->GetData( texFile, (void**) &data, m_width, m_height, m_format, m_type );
	if ( read <= 0 || data == NULL ) {
		Release ();
		DEBUG_LOG ( "ERROR: [TEXURE] Can not load file '%s'\n", filename.c_str() );
		return false;
	}

	GLenum internalFormat;

	switch(m_format)
	{
	case GL_RGBA:
	case GL_BGRA:
		internalFormat = GL_RGBA;
		break;

	case GL_RGB:
	case GL_BGR:
	default:
		internalFormat = GL_RGB;
	}
	
	glTexImage2D ( GL_TEXTURE_2D, 0, internalFormat, m_width, m_height, 0, m_format, m_type, (void*) data );
	GL_CHECK_ERRORS();
	SAFE_DEL( data );

	//TODO - MipMap stuff
	//if( mipmap )
	//{
	//	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
	//	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST );
	//}
	//else
	{
		glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		GL_CHECK_ERRORS();
		glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		GL_CHECK_ERRORS();
	}

	GL_CHECK_ERRORS();
	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	GL_CHECK_ERRORS();
	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
	GL_CHECK_ERRORS();

	//if ( mipmap /*&& oglVersion() >= 3.0f*/ )
	//{
	//	glGenerateMipmapEXT ( GL_TEXTURE_2D );
	//}

	setLoaded(true);
	m_filename = filename;
	return isLoaded ();
}

//-----------------------------------------------------------------------------

GLuint	Texture::GetTextureId()
{
	return m_texID;
}

//-----------------------------------------------------------------------------

void Texture::bind ( GLenum texture )
{
	if ( isLoaded () )
	{
		if( texture )
		{
			if( glewIsSupported("GL_VERSION_2_0") 
				&& glActiveTexture!=NULL )
			{
				glActiveTexture ( texture );
				GL_CHECK_ERRORS();
			}
			else
			{
				DEBUG_ERR("[Texture] glActiveTexture is not supported!\n");
			}
		}
		glBindTexture ( GL_TEXTURE_2D, m_texID );
		GL_CHECK_ERRORS();
	}
}

//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
/*
bool WinTGASave ( char *fileName, int width, int height, char* image )
{
	if( !(width>0 && height>0 && fileName!=NULL && image!=NULL) )
	{
		return false;
	}

	FILE        *fp;
	TGA_HEADER   Header;

	fopen_s ( &fp, fileName, "wb" );
	if ( fp == NULL )
	{
		return false;
	}

	memset( &Header, 0, sizeof(TGA_HEADER) );

	Header.ImageType = 2;
	Header.Width = width;
	Header.Height = height;
	Header.ColorDepth = 24;

	fwrite ( &Header, sizeof(TGA_HEADER), 1, fp );

	RGBTRIPLE *Buffer24 = NULL;
	Buffer24 = (RGBTRIPLE*)malloc(sizeof(RGBTRIPLE) * width * height);

	if(Buffer24)
	{
		int i=0;
		int x,
			y;

		for ( y = 0; y < height; y++ )
		{
			for( x = 0; x < width; x++ )
			{
				int Index = y * width + x;

				if(!(Header.Descriptor & INVERTED_BIT))
					Index = (height - 1 - y) * width + x;

				Buffer24[Index].rgbtRed		=	image[(i * 3)];
				Buffer24[Index].rgbtGreen	=	image[(i * 3) + 1];
				Buffer24[Index].rgbtBlue	=	image[(i * 3) + 2];

				i++;
			}
		}

		fwrite(Buffer24, sizeof(RGBTRIPLE), width * height, fp);
		free(Buffer24);
	}
	else
	{
		fclose(fp);
		return false;
	}
	fclose(fp);

	return true;
}
*/